<?php

declare(strict_types=1);

namespace App\CustHub\Service;

use App\CustHub\Mapper\ChRoomMemberWarningMapper;
use App\Robot\Dto\CommonJobDto;
use App\Robot\Job\CommonJob;
use Carbon\Carbon;
use FriendsOfHyperf\Lock\Exception\LockTimeoutException;
use Mine\Abstracts\AbstractService;
use function FriendsOfHyperf\Lock\lock;
use function Hyperf\Support\optional;

/**
 * 群成员警告服务
 */
class ChRoomMemberWarningService extends AbstractService
{
    public $mapper;

    public function __construct(ChRoomMemberWarningMapper $mapper)
    {
        $this->mapper = $mapper;
    }

    /**
     * 处理违规
     * @param int $uid
     * @param int $mainUid
     * @param string $fromRoomId
     * @param string $userId
     * @param int $robotId
     * @param int $unit
     * @param int $value
     * @return bool
     */
    public function handleViolation(int $uid,int $mainUid,string $fromRoomId, string $userId, int $robotId,mixed $unit,mixed $value,mixed $warningCount): bool
    {
        $lock = lock('rm_warning_'.$fromRoomId.'_'.$userId.'_'.$robotId, 4);
        try {
            $lock->block(2);

            $warning = $this->mapper->model::query()
                ->where('from_room_id', $fromRoomId)
                ->where('user_id', $userId)
                ->where('robot_id', $robotId)
                ->first();

            if(!$warning){
                $warning = $this->mapper->getModel();
                $warning->uid = $uid;
                $warning->main_uid = $mainUid;
                $warning->from_room_id = $fromRoomId;
                $warning->user_id = $userId;
                $warning->robot_id = $robotId;
            }elseif($this->shouldRestCount($warning)){
                $warning->count = 0;
            }

            $warning->rest_count_time = $this->getRestTime($unit,$value);

            // 增加警告次数
            $warning->count++;

            // 处理踢出逻辑
            $shouldKickUser = false;
            if ($warning->count >= $warningCount) {
                $shouldKickUser = true;
                $warning->count = 0;  // 重置计数器
            }

            $rst = $warning->save();
            if($rst){
                $id = $warning->id;
                if($unit == 4){
                    //秒的情况
                    container()->get(LowQueueService::class)->push(new CommonJob(new CommonJobDto(
                        classname: ChRoomMemberWarningService::class,
                        method: 'restCount',
                        data:[
                            'id' => $id
                        ]
                    )),$value);
                }
            }else{
                $shouldKickUser = false;
            }

            return $shouldKickUser;
        }catch (LockTimeoutException $e){
            //超时不处理
            return false;
        } finally {
            optional($lock)->release();
        }
    }

    /**
     * 判断是否需要重置警告次数
     * @param $warning
     * @return bool
     */
    private function shouldRestCount($warning): bool
    {
        return $warning->rest_count_time >= time();
    }

    /**
     * 判断是否需要重置警告次数
     * @param mixed $unit
     * @param mixed $value
     * @return int
     */
    private function getRestTime(mixed $unit,mixed $value): int
    {
        $now = Carbon::now();
        switch ($unit){
            case 1:
                $result = $now->addDays($value)->timestamp;
                break;
            case 2:
                $result = $now->addHours($value)->timestamp;
                break;
            case 3:
                $result = $now->addMinutes($value)->timestamp;
                break;
            default:
                $result = $now->addSeconds($value)->timestamp;
                break;

        }
        return $result;
    }

    /**
     * 重置警告次数
     * @param array $data
     * @return void
     */
    public function restCount(array $data): void
    {
        $id = $data['id'];
        $warning = $this->mapper->model::query()->find($id);
        if($warning && $warning->rest_count_time <= time()){
            $warning->count = 0;
            $warning->save();
        }
    }

    /**
     * 清理过期的警告次数
     * @return void
     */
    public function clearRoomWarnings(): void
    {
        $this->mapper->model::query()
            ->where('rest_count_time','<=',time())
            ->where('count','>',0)
            ->update([
                'count' => 0
            ]);
    }
}